package com.yanqu.road.logic.rank;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.enums.eBigRankType;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.UserRank;
import com.yanqu.road.logic.bussiness.player.UserSacrificeBussiness;
import com.yanqu.road.logic.bussiness.rank.RankBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.RankPb;
import com.yanqu.road.logic.sort.RankSort;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.Comparator;
import java.util.LinkedList;

public class RankListModel {

    private int rankNum = GameConfig.RANK_DEFAULT_MAX_COUNT;

    private Comparator rankSort;

    private boolean isUpdate = false;

    private LinkedList<UserRank> rankList;

    private int bigRankType;

    private int rankType;

    private RankProto.RankListMsg.Builder rankListMsg;

    private static RandomHelper worshipRandom = new RandomHelper();

    public RankListModel(int bigRankType, int rankType) {
        rankSort = new RankSort();
        rankList = new LinkedList<>();
        rankListMsg = RankProto.RankListMsg.newBuilder();
        this.rankType = rankType;
        this.bigRankType = bigRankType;
    }

    public RankListModel(int bigRankType, int rankType, Comparator comparator) {
        rankSort = comparator;
        rankList = new LinkedList<>();
        rankListMsg = RankProto.RankListMsg.newBuilder();
        this.rankType = rankType;
        this.bigRankType = bigRankType;
    }

    public void initRankList() {
        if ((bigRankType == eBigRankType.Normal.getValue() && rankType < 1000) ||
                bigRankType == eBigRankType.Skin.getValue() ||
                bigRankType == eBigRankType.Vehicle.getValue() ||
                bigRankType == eBigRankType.Patrons.getValue() ||
                bigRankType == eBigRankType.Beauty.getValue() ||
                bigRankType == eBigRankType.CurioItem.getValue()
        ) {
            rankList = RankBussiness.getUserRankList(rankType);
        }
        initRankMsg();
    }

    public int getRankType() {
        return rankType;
    }

    public int getBigRankType() {
        return bigRankType;
    }

    public RankProto.RankListMsg.Builder getRankListMsg() {
        return rankListMsg;
    }

    public LinkedList<UserRank> getRankList() {
        return rankList;
    }

    public void setRankList(LinkedList<UserRank> userRankList) {
        synchronized (this) {
            rankList = userRankList;
            initRankMsg();
        }
    }

    private void initRankMsg() {
        rankListMsg = RankPb.parseRankListMsg(rankList);
    }

    //加锁获取排行，领取排行奖励时一定要用这个
    public int getMyRank(long userId) {
        synchronized (this) {
            return unlockGetMyRank(userId);
        }
    }

    //不加锁获取排行榜
    public int unlockGetMyRank(long userId) {
        int i = 0;
        for(UserRank userRank : rankList){
            if(userRank.getUserId() == userId && !userRank.isDelete()){
                return i + 1;
            }
            i++;
        }
        return -1;
    }

    public UserRank getPlayerUserRank(long userId) {
        synchronized (this) {
            for(UserRank userRank : rankList){
                if(userRank.getUserId() == userId && !userRank.isDelete()){
                    return userRank;
                }
            }
            return null;
        }
    }

    public UserRank getFirstRank(){
        if(rankList.size() > 0){
            return rankList.get(0);
        }
        return null;
    }

    public UserRank getWorshipRankData() {
        if (rankList.size() > 0) {
            int sumValue = 0;
            for (int i = 0; i < rankList.size(); i++) {
                sumValue += (rankNum - i);
            }
            int randomValue = worshipRandom.next(0, sumValue);
            int weight = 0;
            int result = 0;
            for (int i = 0; i < rankList.size(); i++) {
                weight += (rankNum - i);
                if (randomValue <= weight) {
                    result = i;
                    break;
                }
            }
            return rankList.get(result);
        }
        return null;
    }

    /**
     * 添加到排行
     * @param lastUpdateTime 秒
     */
    public UserRank rankChange(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param, long lastUpdateTime) {
        boolean isChange = false;
        UserRank userRank = null;
        synchronized (this) {
            int size = rankList.size();
            if (null == getPlayerUserRank(userId)) {
                if (size < rankNum) {
                    userRank = initRank(userId, userBaseInfo, value, param, lastUpdateTime);
                    rankList.add(userRank);
                    isChange = true;
                } else {
                    userRank = initRank(userId, userBaseInfo, value, param, lastUpdateTime);
                    if(rankSort.compare(userRank, rankList.getLast()) < 0){
                        userRank = replaceLastRank(userId, userBaseInfo, value, param, lastUpdateTime);
                        isChange = true;
                    }
                }
            } else {
                for (UserRank tempRank : rankList) {
                    if (tempRank.getUserId() == userId) {
                        tempRank.setLastUpdateTime(lastUpdateTime);
                        tempRank.setValue(value);
                        tempRank.setUserBaseInfo(userBaseInfo);
                        tempRank.setParam(param);
                        tempRank.setDelete(false);
                        userRank = tempRank;
                        break;
                    }
                }
                isChange = true;
            }
            if(isChange) {
                rankList.sort(rankSort);
                initRankMsg();
                isUpdate = true;
            }
        }
        return userRank;
    }

    /**
     * 添加到排行
     */
    public UserRank rankChange(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param) {
        boolean isChange = false;
        UserRank userRank = null;
        synchronized (this) {
            int size = rankList.size();
            if (null == getPlayerUserRank(userId)) {
                if (size < rankNum) {
                    userRank = initRank(userId, userBaseInfo, value, param);
                    rankList.add(userRank);
                    isChange = true;
                } else {
                    userRank = initRank(userId, userBaseInfo, value, param);
                    if(rankSort.compare(userRank, rankList.getLast()) < 0){
                        userRank = replaceLastRank(userId, userBaseInfo, value, param);
                        isChange = true;
                    }
                }
            } else {
                for (UserRank tempRank : rankList) {
                    if (tempRank.getUserId() == userId) {
                        // 影响排行的值变化时，才更新时间
                        if (isRankDataChange(tempRank, value, param)) {
                            tempRank.setLastUpdateTime(System.currentTimeMillis() / 1000);
                        }
                        tempRank.setValue(value);
                        tempRank.setUserBaseInfo(userBaseInfo);
                        tempRank.setParam(param);
                        tempRank.setDelete(false);
                        userRank = tempRank;
                        break;
                    }
                }
                isChange = true;
            }
            if(isChange) {
                rankList.sort(rankSort);
                initRankMsg();
                isUpdate = true;
            }
        }
        return userRank;
    }

    /**
     * 添加到排行
     */
    public UserRank allPatronsRankChange(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param) {
        boolean isChange = false;
        UserRank userRank = null;
        int patronsId = JSONObject.parseObject(param).getIntValue("patronsId");
        synchronized (this) {
            int size = rankList.size();
            if (!rankList.stream().anyMatch(predicate -> predicate.getUserId() == userId && JSONObject.parseObject(predicate.getParam()).getIntValue("patronsId") == patronsId)) {
                if (size < rankNum) {
                    userRank = initRank(userId, userBaseInfo, value, param);
                    rankList.add(userRank);
                    isChange = true;
                } else if (rankList.getLast().getValue().compareTo(value) < 0) {
                    userRank = replaceLastRank(userId, userBaseInfo, value, param);
                    isChange = true;
                } else if ((bigRankType == eBigRankType.Skin.getValue() || bigRankType == eBigRankType.Patrons.getValue() || bigRankType == eBigRankType.Beauty.getValue()) && rankList.getLast().getValue().compareTo(value) == 0) {
                    JSONObject lastObject = JSONObject.parseObject(rankList.getLast().getParam());
                    JSONObject curObject = JSONObject.parseObject(param);
                    BigInteger vLast = StringUtils.isNullOrEmpty(lastObject.getString("value")) ? BigInteger.ZERO : lastObject.getBigInteger("value");
                    BigInteger vCur = StringUtils.isNullOrEmpty(curObject.getString("value")) ? BigInteger.ZERO : curObject.getBigInteger("value");
                    if (vLast.compareTo(vCur) < 0) {
                        userRank = replaceLastRank(userId, userBaseInfo, value, param);
                        isChange = true;
                    }
                } else if (bigRankType == eBigRankType.Vehicle.getValue() && rankList.getLast().getValue().compareTo(value) == 0) {
                    JSONObject lastObject = JSONObject.parseObject(rankList.getLast().getParam());
                    JSONObject curObject = JSONObject.parseObject(param);
                    // 赚钱比较
                    int lastAddi = StringUtils.isNullOrEmpty(lastObject.getString("addition")) ? 0 : lastObject.getInteger("addition");
                    int curAddi = StringUtils.isNullOrEmpty(curObject.getString("addition")) ? 0 : curObject.getInteger("addition");
                    if (curAddi > lastAddi) {
                        userRank = replaceLastRank(userId, userBaseInfo, value, param);
                        isChange = true;
                    }
                }
            } else {
                for (UserRank tempRank : rankList) {
                    if (tempRank.getUserId() == userId && JSONObject.parseObject(tempRank.getParam()).getIntValue("patronsId") == patronsId) {
                        // 影响排行的值变化时，才更新时间
                        if (isRankDataChange(tempRank, value, param)) {
                            tempRank.setLastUpdateTime(System.currentTimeMillis() / 1000);
                        }
                        tempRank.setValue(value);
                        tempRank.setUserBaseInfo(userBaseInfo);
                        tempRank.setParam(param);
                        tempRank.setDelete(false);
                        userRank = tempRank;
                        break;
                    }
                }
                isChange = true;
            }
            if(isChange) {
                rankList.sort(rankSort);
                initRankMsg();
                isUpdate = true;
            }
        }
        return userRank;
    }

    /**
     * 添加到排行
     * @param lastUpdateTime 秒
     */
    public UserRank allRankChange(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param, long lastUpdateTime) {
        boolean isChange = false;
        UserRank userRank = null;
        int id = JSONObject.parseObject(param).getIntValue("id");
        synchronized (this) {
            int size = rankList.size();
            if (!rankList.stream().anyMatch(predicate -> predicate.getUserId() == userId && JSONObject.parseObject(predicate.getParam()).getIntValue("id") == id)) {
                if (size < rankNum) {
                    userRank = initRank(userId, userBaseInfo, value, param, lastUpdateTime);
                    rankList.add(userRank);
                    isChange = true;
                } else if (rankList.getLast().getValue().compareTo(value) < 0) {
                    userRank = replaceLastRank(userId, userBaseInfo, value, param, lastUpdateTime);
                    isChange = true;
                }
            } else {
                for (UserRank tempRank : rankList) {
                    if (tempRank.getUserId() == userId && JSONObject.parseObject(tempRank.getParam()).getIntValue("id") == id) {
                        tempRank.setLastUpdateTime(lastUpdateTime);
                        tempRank.setValue(value);
                        tempRank.setUserBaseInfo(userBaseInfo);
                        tempRank.setParam(param);
                        tempRank.setDelete(false);
                        userRank = tempRank;
                        break;
                    }
                }
                isChange = true;
            }
            if(isChange) {
                rankList.sort(rankSort);
                initRankMsg();
                isUpdate = true;
            }
        }
        return userRank;
    }

    /**
     * 添加到排行
     */
    public UserRank allBeautyRankChange(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param) {
        boolean isChange = false;
        UserRank userRank = null;
        int id = JSONObject.parseObject(param).getIntValue("id");
        synchronized (this) {
            int size = rankList.size();
            if (!rankList.stream().anyMatch(predicate -> predicate.getUserId() == userId && JSONObject.parseObject(predicate.getParam()).getIntValue("id") == id)) {
                if (size < rankNum) {
                    userRank = initRank(userId, userBaseInfo, value, param);
                    rankList.add(userRank);
                    isChange = true;
                } else if (rankList.getLast().getValue().compareTo(value) < 0) {
                    userRank = replaceLastRank(userId, userBaseInfo, value, param);
                    isChange = true;
                } else if (bigRankType == eBigRankType.Beauty.getValue() && rankList.getLast().getValue().compareTo(value) == 0) {
                    JSONObject lastObject = JSONObject.parseObject(rankList.getLast().getParam());
                    JSONObject curObject = JSONObject.parseObject(param);
                    BigInteger vLast = StringUtils.isNullOrEmpty(lastObject.getString("value")) ? BigInteger.ZERO : lastObject.getBigInteger("value");
                    BigInteger vCur = StringUtils.isNullOrEmpty(curObject.getString("value")) ? BigInteger.ZERO : curObject.getBigInteger("value");
                    if (vLast.compareTo(vCur) < 0) {
                        userRank = replaceLastRank(userId, userBaseInfo, value, param);
                        isChange = true;
                    }
                } else if (bigRankType == eBigRankType.CurioItem.getValue() && rankList.getLast().getValue().compareTo(value) == 0) {

                }
            } else {
                for (UserRank tempRank : rankList) {
                    if (tempRank.getUserId() == userId && JSONObject.parseObject(tempRank.getParam()).getIntValue("id") == id) {
                        // 影响排行的值变化时，才更新时间
                        if (isRankDataChange(tempRank, value, param)) {
                            tempRank.setLastUpdateTime(System.currentTimeMillis() / 1000);
                        }
                        tempRank.setValue(value);
                        tempRank.setUserBaseInfo(userBaseInfo);
                        tempRank.setParam(param);
                        tempRank.setDelete(false);
                        userRank = tempRank;
                        break;
                    }
                }
                isChange = true;
            }
            if(isChange) {
                rankList.sort(rankSort);
                initRankMsg();
                isUpdate = true;
            }
        }
        return userRank;
    }

    public boolean removeUserRank(long userId) {
        boolean isChange = false;
        synchronized (this){
            for(UserRank userRank : rankList){
                if(userRank.getUserId() == userId){
                    userRank.setUserId(0);
                    userRank.setValue(BigInteger.ZERO);
                    if (bigRankType == eBigRankType.Vehicle.getValue()) {
                        userRank.setValue(BigInteger.valueOf(Long.MIN_VALUE));
                    }
                    userRank.setDelete(true);
                    isChange = true;
                    break;
                }
            }
            if(isChange) {
                rankList.sort(rankSort);
                initRankMsg();
                isUpdate = true;
            }
        }
        return isChange;
    }

    /**
     * 用户信息变化
     */
    public void changeUserInfo(long userId, UserBaseInfo userBaseInfo) {
        synchronized (this) {
            rankList.forEach(action -> {
                if (action.getUserId() == userId) {
                    action.setUserBaseInfo(userBaseInfo);
                    action.setLastUpdateTime(System.currentTimeMillis() / 1000);
                    initRankMsg();
                    isUpdate = true;
                }
            });
        }
    }

    public UserRank initRank(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param) {
        UserRank rank = new UserRank();
        rank.setUserId(userId);
        rank.setUserBaseInfo(userBaseInfo);
        rank.setValue(value);
        rank.setType(rankType);
        rank.setBigRankType(bigRankType);
        rank.setLastUpdateTime(System.currentTimeMillis() / 1000);
        rank.setParam(param);
        rank.setDelete(false);
        return rank;
    }

    public UserRank initRank(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param, long lastUpdateTime) {
        UserRank rank = new UserRank();
        rank.setUserId(userId);
        rank.setUserBaseInfo(userBaseInfo);
        rank.setValue(value);
        rank.setType(rankType);
        rank.setBigRankType(bigRankType);
        rank.setLastUpdateTime(lastUpdateTime);
        rank.setParam(param);
        rank.setDelete(false);
        return rank;
    }

    public void setRankNum(int rankNum) {
        this.rankNum = rankNum;
    }

    public void saveNormalRankList() {
        LinkedList<UserRank> newRankList;
        synchronized (this) {
            if (!isUpdate) {
                return;
            }
            newRankList = new LinkedList<>(rankList);
            isUpdate = false;
        }
        RankBussiness.updateUserRankList(newRankList);
    }

    public void saveSacrificeDamageRankList(){
        LinkedList<UserRank> newRankList;
        synchronized (this) {
            if (!isUpdate) {
                return;
            }
            newRankList = new LinkedList<>(rankList);
            isUpdate = false;
        }
        UserSacrificeBussiness.updateSacrificeDamageRankList(newRankList);
    }

    /**
     * 替换榜单最后一名
     */
    private UserRank replaceLastRank(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param) {
        UserRank last = rankList.getLast();
        last.setUserId(userId);
        last.setUserBaseInfo(userBaseInfo);
        last.setValue(value);
        last.setLastUpdateTime(System.currentTimeMillis() / 1000);
        last.setParam(param);
        last.setDelete(false);
        return last;
    }

    /**
     * 替换榜单最后一名
     */
    private UserRank replaceLastRank(long userId, UserBaseInfo userBaseInfo, BigInteger value, String param, long lastUpdateTime) {
        UserRank last = rankList.getLast();
        last.setUserId(userId);
        last.setUserBaseInfo(userBaseInfo);
        last.setValue(value);
        last.setLastUpdateTime(lastUpdateTime);
        last.setParam(param);
        last.setDelete(false);
        return last;
    }

    /**
     * 排行数据是否变化
     */
    private boolean isRankDataChange(UserRank oldRank, BigInteger value, String param) {
        UserRank newRank = new UserRank();
        newRank.setBigRankType(oldRank.getBigRankType());
        newRank.setType(oldRank.getType());
        newRank.setRank(oldRank.getRank());
        newRank.setUserId(oldRank.getUserId());
        newRank.setUserBaseInfo(oldRank.getUserBaseInfo());
        newRank.setLastUpdateTime(oldRank.getLastUpdateTime());
        // 影响排行榜的值
        newRank.setValue(value);
        newRank.setParam(param);
        return rankSort.compare(oldRank, newRank) != 0;
    }
}
